import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;


public class Ex2_4 {


	//CYCLOPEPTIDESEQUENCING(Spectrum)
	//List <- {0-peptide}
	//while List is nonempty
	//    List <- Expand(List)
	//    for each peptide Peptide in List
	//        if Cyclospectrum(Peptide) = Spectrum
	//            output Peptide
	//            remove Peptide from List
	//        else if Peptide is not consistent with Spectrum
	//            remove Peptide from List
	//	

	private ArrayList<Integer> masses;
	private ArrayList<Integer> spectre;
	private ArrayList<ArrayList<Integer>> finalPeps;

	public Ex2_4() {		
		masses = new ArrayList<Integer>();
		spectre = new ArrayList<Integer>();
		finalPeps = new ArrayList<ArrayList<Integer>>();
		loadMasses("C:\\Users\\josemfer\\Downloads\\integer_mass_table.txt");
		loadSpectre("C:\\Users\\josemfer\\Downloads\\cycloseq_data.txt");
	}


	public void cyclosequence() {
		ArrayList<ArrayList<Integer>> plist = new ArrayList<ArrayList<Integer>>();
		ArrayList<Integer> cerolist = new ArrayList<Integer>();
		cerolist.add(0);
		plist.add(cerolist);		
		

		ArrayList<Integer> newmasses = new ArrayList<Integer>();
		// remove non used bases
		for (Integer m : this.masses) {
			if (this.spectre.contains(m)) {
				newmasses.add(m);
			}			
		}
		this.masses = newmasses;
		
		
		while (plist != null && plist.size() > 0) {
			plist = expand(plist);			
			
			
			// FOR BEGIN
			ArrayList<ArrayList<Integer>> newplist = (ArrayList<ArrayList<Integer>>) plist.clone();
			for (ArrayList<Integer> pep : newplist) {
				ArrayList<Integer> spec = getCyclospectrum(pep);
				if (spectre.containsAll(spec) &&
						spec.containsAll(spectre)
						) {
					if (!finalPeps.contains(pep)) {
						finalPeps.add(pep);
						System.out.println(pep);
					}
					plist.remove(pep);
				} else if (!isConsistent(pep)) {
					plist.remove(pep);					
				}
			} // FOR END
		}

		System.out.println(finalPeps);
	}


	private ArrayList<ArrayList<Integer>> 
	expand(ArrayList<ArrayList<Integer>> oldList) {
		ArrayList<ArrayList<Integer>> newList = new ArrayList<ArrayList<Integer>>();
		for (ArrayList<Integer> l : oldList) {
			for (Integer m : this.masses) {
				ArrayList<Integer> pep = new ArrayList<Integer>();
				if (oldList.size() > 1) {
					pep.addAll(l);
				}
				pep.add(m);
				newList.add(pep);
			}
		}	


		return newList;		
	}

	private boolean isConsistent(ArrayList<Integer> peptide) {
		int sum = 0;
		for (int pep : peptide) {
			sum += pep;
		}
		if (this.spectre.contains(sum)) {
			return true;
		} 		
		return false;
	}

	public ArrayList<Integer> getCyclospectrum(ArrayList<Integer> peptide) {
		ArrayList<Integer> sp = new ArrayList<Integer>();	
		sp.add(0);	
		ArrayList<Integer> cyclop = new ArrayList<Integer>();
		cyclop.addAll(peptide);
		cyclop.addAll(peptide);		
		for (int i=1;i<peptide.size()+1;i++) { // i-mer
			for (int j=0;j<peptide.size();j++) {
				int sum = 0;				
				// sum elements in sub list
				for (int s : cyclop.subList(j, j+i)) {
					sum += s;
				}				
				sp.add(sum);
				if (i == peptide.size()) {
					break;					
				}
			}		
		}		
		Collections.sort(sp);
		return sp;	
	}


	private void loadSpectre(String file) {		
		try {
			String inputFile = KmerCounter.readFile(file);
			for (String s : inputFile.split("\\s+")) {
				spectre.add(Integer.valueOf(s));
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}

	private void loadMasses(String file) 
	{		
		try {
			HashMap<String, String> hm = new HashMap<String, String>();
			BufferedReader reader = new BufferedReader( new FileReader (file));
			String         line = null;				
			while( ( line = reader.readLine() ) != null ) {			
				String[] l = line.split("\\s+");
				if (!masses.contains(l[1])) {
					masses.add(Integer.valueOf(l[1]));
				}				
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 			
	}	




	public static void main(String[] args) {
		Ex2_4 exer = new Ex2_4();
		exer.cyclosequence();

	}	


}
